#include "vtkFieldImport.hpp"
#include "vtkFunctions.hpp"

namespace hms::vtk
{


/* Returns a vector of function parsers, because functions strings can contain 
 * the z-coordinate as a variable. The z-coordinate is not known yet, but if
 * it is prioritised, then other functions can be evaluated with it */
template<typename MeshType>
std::vector<FunctionParserWrapper> readDomainValues(
	const xml::XMLElement* cellData,
	Field<MeshType>& field,
	const std::string& fieldName
){
	Index nComponents { field.nComponents() };

	const xml::XMLElement* fieldElem {
		findFieldData(cellData, fieldName, nComponents )
	};

	bool
		isUniform { getAttributeValueWithDefault(fieldElem, "isUniform", false) },
		isFunction { getAttributeValueWithDefault(fieldElem, "isFunction", false) };

	if ( !isUniform && !isFunction ){
		/* value list */
		textToMatrix( fieldElem, field.domainValues() );
	} else if ( isUniform ){
		/* uniform initialisation, either by value or by function */
		ArrayXs domainVal ( nComponents );
		if ( !isFunction ){
			/* uniform value */
			textToMatrix( fieldElem, domainVal );
		} else {
			/* uniform function (one function per component, evaluated once) */
			warning(
				"Field \"" + fieldName + "\": Evaluating domain field "
				"values as uniform function! All variables (" +
				FunctionParserWrapper::allVars() + ") are set to zero!"
			);
			for ( Index i{0}; i < nComponents; ++i ){
				FunctionParserWrapper fp { readFunction(fieldElem, i, false) };
				/* evaluated with all variables set to zero (default) */
				domainVal[i] = fp.eval();
			}
		}
		field.domainValues().colwise() = domainVal;
	} else {
		/* non-uniform function */
		std::vector<FunctionParserWrapper> functions {
			readFunctions(fieldElem, nComponents, false)
		};
		return functions;
	}
	return {};
}

#define INSTANTIATE_FOR_ALL_MESHTYPES(MeshType) \
template std::vector<FunctionParserWrapper> readDomainValues( \
	const xml::XMLElement*, Field<MeshType>&, const std::string& );

#include "meshInstantiator.hpp"

} // namespace hms::vtk
